home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
assemblr
/
library
/
wakeup
/
wakeup.asm
next >
Wrap
Assembly Source File
|
1988-04-25
|
9KB
|
306 lines
;-------------------------------------------------------
; WAKEUP.ASM -- OS/2 Detachable Alarm Program
; Copyright (c) 1988, Ziff Communications Co.
; PC Magazine * Charles Petzold
;-------------------------------------------------------
.286C
DOSSEG
.MODEL SMALL
.STACK 0200h
; ---------------------------------------------
; OS/2 External Functions and Data Structures
; ---------------------------------------------
EXTRN DosBeep:FAR, DosExit:FAR, DosGetDateTime:FAR EXTRN DosSleep:FAR, DosWrite:FAR, KbdCharIn:FAR
EXTRN KbdFlushBuffer:FAR, VioEndPopUp:FAR, VioPopUp:FAR
EXTRN VioSetCurPos:FAR, VioWrtNAttr:FAR, VioWrtTTY:FAR,
DateTimeStruc STRUC
hour db ?
minutes db ?
seconds db ?
hundreths db ?
day db ?
month db ?
year dw ?
timezone dw ?
day_of_week db ?
DateTimeStruc ENDS
KeyDataStruc STRUC
char_code db ?
scan_code db ?
status db ?
nls_shift db ?
shift_state dw ?
time dd ?
KeyDataStruc ENDS
; --------------------------
.DATA ; Initialized Data Segment
; --------------------------
SyntaxMsg db 13, 10, "Syntax: DETACH WAKEUP hour:minute"
db 13, 10, 10, 9, "Use 24-hour time format."
db 13, 10, 10, "(c) 1988, Ziff Communications Co."
db 13, 10, "PC Magazine ",254, "Charles Petzold"
db 13, 10
SyntaxMsgLen equ $ - SyntaxMsg
db 10, "Press any key to return to OS/2..."
SyntaxMsgLen2 equ $ - SyntaxMsg
WakeupMsg db "WAKE UP! WAKE UP! WAKE UP!"
WakeupMsgLen equ $ - WakeupMsg
Delimiters db 9, " ,;="
PopupFlag dw 1
Attribute db 4Fh, 74h
; ----------------------------
.DATA? ; Uninitialized Data Segment
; ----------------------------
BytesWritten dw ?
DateTime DateTimeStruc <>
KeyData KeyDataStruc <>
; --------------
.CODE ; Code Segment
; --------------
ASSUME ES:DGROUP
; ---------------------------------------------
; Parse command line to find the wake-up time
; ---------------------------------------------
Entry: Push DS ; Data segment selector
Pop ES ; Transfer it to ES
Mov DS, AX ; DS = Environment selector
Mov SI, BX ; SI = Start of command line
Sub AH, AH ; A little preparation
; Skip name and delimiters
; ------------------------
SkipProgName: Lodsb ; Pull a command line byte
Or AL, AL ; Check if it's zero
Jnz SkipProgName ; If not, continue
SkipDelims: Lodsb ; Get another byte
Or AL, AL ; See if it's zero
Jz ParamError ; If so, that's no good
Mov DI, Offset Delimiters ; All possible delimiters
Mov CX, 5 ; Five of them
Repnz Scasb ; Scan for a match
Jz SkipDelims ; If match, try another byte
; Calculate Hour
; --------------
Call NumberTrans ; Translate ASCII byte
Mov DX, AX ; Save first 'hour' byte in DL
Lodsb ; Get second 'hour' byte
Cmp AL, ':' ; See if it'a a colon
Jz GotHour ; If so, hour is finished
Call NumberTrans ; If not, translate it
IMul DX, 10 ; Multiply first byte by 10
Add DL, AL ; Add the second byte
Cmp DL, 24 ; Check if hour is 24 or above
Jae ParamError ; What clock do you use?
Lodsb ; Get next byte
Cmp AL, ':' ; Should be colon
Jnz ParamError ; If not, it's an error
GotHour: IMul DX, 60 ; DX has minutes since midnight
; Calculate Minutes
; -----------------
Lodsb ; First 'minutes' byte
Call NumberTrans ; Translate it
IMul AX, 10 ; Multiply by 10
Mov AH, AL ; And save in AH
Lodsb ; Second 'minutes' byte
Call NumberTrans ; Translate it
Add AL, AH ; Add the two
Cmp AL, 60 ; Check if minutes > 60
Jae ParamError ; Another bizarre clock
Sub AH, AH ; Zero out AH
Add DX, AX ; Parameter time in minutes
Jmp Short GetCurrentTime ; All done with parsing
; -----------------------------------------------------
; Display 'syntax' message if an error is encountered
; -----------------------------------------------------
ParamError: Push ES ; Restore DS to
Pop DS ; data segment
Mov CX, SyntaxMsgLen ; Length of text
WriteSyntaxMsg: Push 1 ; Handle is standard error
Push DS ; Segment of text
Push Offset SyntaxMsg ; Offset of text
Push CX ; Length of text
Push DS ; Segment of bytes written
Push Offset BytesWritten ; Offset of bytes written
Call DosWrite ; Write the error message
Cmp CX, SyntaxMsgLen2 ; Check if second time through
Jz EndPopup ; If so, wait for keystroke
Or AX, AX ; If no error, simply exit
Jz ErrorExit
Push DS ; Segment of PopupFlag
Push Offset PopupFlag ; Offset of PopupFlag
Push 0 ; Video handle always zero
Call VioPopUp ; Popup on screen
Mov CX, SyntaxMsgLen2 ; Text length for popup version
Jmp WriteSyntaxMsg ; Go to it
EndPopup: Push DS ; Segment of KeyData struc
Push Offset KeyData ; Offset of KeyData struc
Push 0 ; Wait for keystroke
Push 0 ; Keyboard handle
Call KbdCharIn ; Fetch a key
Push 0 ; Video handle
Call VioEndPopUp ; End the popup
ErrorExit: Push 1 ; Terminate all threads
Push 1 ; Return error code of 1
Call DosExit ; And exit
; ---------------------------------------------------------------------
; NumberTrans Subroutine -- Translates ASCII to Hex (CY set if error)
; ---------------------------------------------------------------------
NumberTrans: Sub AL, '0' ; ASCII to hex
Jc ParamError ; Error if under 0
Cmp AL, 9 ; Also error if over 9
Ja ParamError
BadNumberTrans: Ret
; ---------------------------------------------------------
; Get current time, calculate difference, and go to sleep
; ---------------------------------------------------------
GetCurrentTime: Push ES ; Restore DS to data segment
Pop DS
Push DS ; Push segment address
Push Offset DateTime ; Push offset of structure
Call DosGetDateTime ; Get current date and time
Mov AL, DateTime.hour ; AL is current hour
Sub AH, AH ; Zero out top byte
IMul AX, 60 ; AX is minutes since midnight
Add AL, DateTime.minutes ; Add the current minutes
Adc AH, 0 ; And carry into top byte
Xchg AX, DX ; Subtract parameter time
Sub AX, DX ; from current time
Jnc DifferenceOK ; OK if both after midnight
Add AX, 24 * 60 ; Otherwise add whole day
DifferenceOK: Mov DX, 60 * 1000 ; Milliseconds in 1 minute
Mul DX ; DX:AX = interval in msec
Push DX ; Push high word
Push AX ; Push low word
Call DosSleep ; And take a long long nap
; -----------------------------------------------------
; On return from DosSleep, start beeping and flashing
; -----------------------------------------------------
Push DS ; Segment of flag
Push Offset PopupFlag ; Offset of flag
Push 0 ; Video handle always 0
Call VioPopUp ; Pop up!
Mov AX, 80 ; 80 columns across screen
Sub AX, WakeupMsgLen ; Less the length of message Shr AX, 1 ; Divide by two for margin
Push 12 ; Row (near the center)
Push AX ; Column to center text
Push 0 ; Video handle
Call VioSetCurPos ; Set the cursor
Push DS ; Segment of message
Push Offset WakeupMsg ; Offset of message
Push WakeupMsgLen ; Length of message
Push 0 ; Darn video handle again
Call VioWrtTTY ; Write it out
Push 0 ; Flush keyboard buffer
Call KbdFlushBuffer ; in case user is typing
FlasherLoop: Mov AX, 0 ; Indicates 1st attribute
Mov BX, 512 ; One alternating tone
Mov DX, 1024 ; Second alternating tone
Call RingBell ; Start it going
Mov AX, 1 ; Second attribute
Mov BX, 1024 ; One alternating tone
Mov DX, 2048 ; Second alternating tone
Call RingBell ; Do it again
Push DS ; Segment of KeyData struc
Push Offset KeyData ; Offset of KeyData struc
Push 1 ; Do not wait for keystroke
Push 0 ; Keyboard handle
Call KbdCharIn ; Fetch a key
Mov AL, KeyData.char_code ; Check if character and scn
Or AL, KeyData.scan_code ; code are both zero
Jz FlasherLoop ; If so, no key, so continue
Push 0 ; Video handle
Call VioEndPopUp ; End the popup
Push 1 ; Terminate normally
Push 0 ; With return code for success
Call DosExit
; ---------------------------------------------------------------------
; RingBell Subroutine -- Sets Attribute from AX, Beeps with BX and DX
; ---------------------------------------------------------------------
RingBell: Add AX, Offset Attribute ; Attribute for screen
Push DS ; Segment of attribute
Push AX ; Offset of attribute
Push 25 * 80 ; Number of attributes
Push 0 ; Starting row
Push 0 ; Starting column Push 0 ; Video handle
Call VioWrtNAttr ; Write the attribute
Mov CX, 10 ; Do beeps ten times
RingBell1: Push BX ; Frequency
Push 50 ; Duration
Call DosBeep ; Beep
Push DX ; Frequency
Push 50 ; Duration
Call DosBeep ; Beep
Loop RingBell1 ; Loop around
Ret
END Entry